/*
 * Copyright (C) 2008-2010, fluid Operations GmbH
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.

 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package main;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;

import jp.sbi.celldesigner.plugin.PluginCompartment;
import jp.sbi.celldesigner.plugin.PluginListOf;
import jp.sbi.celldesigner.plugin.PluginModel;
import jp.sbi.celldesigner.plugin.PluginModification;
import jp.sbi.celldesigner.plugin.PluginModificationResidue;
import jp.sbi.celldesigner.plugin.PluginModifierSpeciesReference;
import jp.sbi.celldesigner.plugin.PluginReaction;
import jp.sbi.celldesigner.plugin.PluginSpecies;
import jp.sbi.celldesigner.plugin.PluginSpeciesAlias;
import jp.sbi.celldesigner.plugin.PluginSpeciesReference;
import objects.Modification;
import objects.Reaction;
import objects.ReactionParticipant;
import objects.Species;

/**
 * This class contains all the main logic on the interface to the CellDesginer itself. It extracts the model information and sends
 * it to the TranslationServer or receives information from there and transforms it into the CellDesigner-Model
 * 
 * @author Tobias
 * 
 */
public class ExtractorPluginDialog extends JDialog {

	public ExtractorPluginDialog(ExtractorPlugin _plugin) throws HeadlessException {

		wrapperPanel = null;
		buttonPanel = null;
		plugin = _plugin;
		initialize();
	}

	private void initialize() {
		
		setSize(350, 420);
		setTitle("SBML2SMW");
		JPanel panel = new JPanel();
		setContentPane(panel);
		panel.add(getButtonPanel());
		setAlwaysOnTop(false);

	}

	protected void closeActionPerformed() {
		setVisible(false);
		dispose();
	}

	private JPanel getButtonPanel() {
		
		
		String hostAdressTemp = null;
		
		// SBMLconfig.prop contains all the information necessary to properly run the plugin (see documentation)
		File configFile = new File("SBMLconfig.prop");
		
		try {
			BufferedReader br = new BufferedReader(new FileReader(configFile));
			String line;
			while ((line = br.readLine()) != null) {
				if (line.startsWith("user")) {
					this.user = line.substring(5);
				}
				else if (line.startsWith("pass")) {
					this.pass = line.substring(5);
				}
				else if (line.startsWith("wikiUrl")) {
					this.wikiUrl = line.substring(8);
				}
				else if (line.startsWith("namespace")) {
					this.namespace=line.substring(10);
				}
				else if (line.startsWith("server")) {
					hostAdressTemp = line.substring(7);
				}
				else if (line.startsWith("language")) {
					this.language = line.substring(9);
				}
			}
		} catch (FileNotFoundException e4) {
			e4.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		final String hostAdress = hostAdressTemp;

		JLabel label = new JLabel("<html>Load information about  <br>selected resources from the  <br>Semantic MediaWiki  ");

		buttonPanel = new JPanel();
		buttonPanel.add(label);

		GridLayout layout = new GridLayout(3, 2);

		buttonPanel.setLayout(layout);

		JButton loadButton = new JButton("Load");
		
		/*
		 * When the user clicks Load, all reactions for all selected specieses are searched in the wiki and added to the CellDesigner model
		 */
		loadButton.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {

				setCursor(Cursor.WAIT_CURSOR);
				int layoutColumn = 0;
				int layoutRow = 0;


				PluginModel pm = plugin.getSelectedModel();

				PluginListOf selectedSpecieses = plugin.getSelectedSpeciesNode();

				if (selectedSpecieses.size() == 0) {
					setCursor(Cursor.DEFAULT_CURSOR);
					return;
				}
				
				// for modified specieses, the realNameMap maps them to their base-species, so the species-information can easily
				// be extracted when instantiating the modified species
				Map<String, String> realNameMap = new HashMap<String, String>();

				for (int speciesCount = 0; speciesCount < selectedSpecieses.size(); speciesCount++) {

					PluginSpeciesAlias markedSpecies = (PluginSpeciesAlias) selectedSpecieses.get(speciesCount);
					String name = markedSpecies.getSpecies().getName();
					//since SMW always capitalizes the first letter of entities, this also has to be done with the names of selected specieses
					name = name.substring(0, 1).toUpperCase() + name.substring(1);
					
					PluginListOf mods = markedSpecies.getModifications();
					int k = 0;
					String modString = "";
					while (mods.get(k) != null) {
						// if the marked species has modifications, the actual name of the wiki-entity has to be constructed from
						// the base name and all modifications of the selected species in order to only load the reactions having
						// this specific modification
						modString += "_" + ((PluginModification) mods.get(k)).getState();
						k++;
					}

					URL url;
					try {
						if (!modString.equals("") && !name.contains("_modified_")) {
							modString = "_modified" + modString;
							// here, the mapping of the modification's name to the base name is established
							realNameMap.put(name + modString, name);
						}
						else {
							modString = "";
						}
						
						// the request for everything known to the wiki about the marked soecies. Therefore, we import the RDF
						// representation containing all incoming and outgoing statements of the selected species via 2 hops
						url = new URL(hostAdress + "load/reaction/?name=" + name + modString + "&type="
								+ markedSpecies.getType() + "&protType="
								+ ((markedSpecies.getProtein() != null) ? markedSpecies.getProtein().getType() : "") + "&user=" + ExtractorPluginDialog.this.user + "&pass=" + ExtractorPluginDialog.this.pass + "&wiki=" + ExtractorPluginDialog.this.wikiUrl + "&namespace=" + ExtractorPluginDialog.this.namespace + "&language=" + ExtractorPluginDialog.this.language);
						URLConnection conn = url.openConnection();

						// Get the response
						BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));

						Map<String, String> map = new HashMap<String, String>();

						// this list has to be maintained in order to find out for all the specieses to be loaded if they are
						// already in the model and therefore do not have to be added but only be interlinked
						PluginListOf allSpecies = pm.getListOfSpecies();
						Set<String> allSpeciesNames = new HashSet<String>();

						for (int i = 0; i < allSpecies.size(); i++) {
							PluginSpecies sp = (PluginSpecies) allSpecies.get(i);
							allSpeciesNames.add(sp.getName());
							map.put(sp.getName(), sp.getId());
						}

						PluginListOf allReactions = pm.getListOfReactions();
						Set<String> allReactionsNames = new HashSet<String>();

						for (int i = 0; i < allReactions.size(); i++) {
							PluginReaction reac = (PluginReaction) allReactions.get(i);
							allReactionsNames.add(reac.getName());
							map.put(reac.getName(), reac.getId());

						}

						String line;
						while ((line = rd.readLine()) != null) {
							// if a line starts with the keyword "species", it contains all information about this species from the wiki
							if (line.startsWith("species")) {

								String[] props = line.split(";");
								String speciesType = null;
								String speciesName = null;
								String proteinType = null;
								String annotation = null;

								// extract all this information 
								for (String prop : props) {
									if (prop.startsWith("speciesName")) {
										speciesName = prop.substring(prop.indexOf("=") + 1);
									} else if (prop.startsWith("speciesType")) {
										speciesType = prop.substring(prop.indexOf("=") + 1);
										if (speciesType == null || speciesType.equals("null")) {
											speciesType = "UNKNOWN";
										}
									} else if (prop.startsWith("proteinType")) {
										proteinType = prop.substring(prop.indexOf("=") + 1);
									}
									else if (prop.startsWith("annotation")) {
										annotation = prop.substring(prop.indexOf("=") + 1);
									}

								}
								// if no species of this name is already part of the model, add it to the model, otherwise, the
								// contained one will later be interlinkes
								if (!(allSpeciesNames.contains(speciesName))
										&& !allSpeciesNames.contains(speciesName.substring(0, 1).toLowerCase()
												+ speciesName.substring(1))) {

									layoutRow++;

									String[] speciesMods = null;
									// if the species is modified, we decode all the modifications from its wiki-name
									if (speciesName.contains("_modified_"))
										speciesMods = speciesName.substring(speciesName.indexOf("_modified_") + 10).split("_");
									
									PluginSpecies spec = new PluginSpecies(!proteinType.equals("null") ? proteinType : speciesType, speciesName);

									map.put(speciesName, spec.getId());
									allSpeciesNames.add(speciesName);

									spec.getSpeciesAlias(0).setFramePosition(markedSpecies.getX() + 70 + layoutRow * 100, 30 + layoutColumn * 70);

									// ADD THE SPECIES
									pm.addSpecies(spec);
									plugin.notifySBaseAdded(spec);

									// if the current species is a protein (only those can be modified) and actually has modifications, add them
									if (!proteinType.equals("null") && speciesMods != null && speciesMods.length > 0) {
										PluginListOf modifications = new PluginListOf();
										PluginModificationResidue res = new PluginModificationResidue(spec.getSpeciesAlias(0).getProtein());
										res.setType(speciesMods[0]);
										
										// the plugin has to be notified about every change of a species being part of it (here: the modification-residue)
										spec.getSpeciesAlias(0).getProtein().addPluginModificationResidue(res);
										plugin.notifySBaseChanged(spec.getSpeciesAlias(0).getProtein());
										
										// and here: the kind of modification (phosphorylated, ...)
										modifications.append(new PluginModification(res.getId(), res.getType()));
										spec.getSpeciesAlias(0).setModifications(modifications);
										plugin.notifySBaseChanged(spec.getSpeciesAlias(0));
									}
									spec.setNotes(annotation);
									plugin.notifySBaseChanged(spec.getSpeciesAlias(0));
								}

								// since all information about all participating specieses on a certain reaction are sent to the
								// plugin before the actual information about the reaction itself, on this point, we assured that
								// all reactants and products are in the model. Loading the reaction itself means then only
								// interlinking all its participants
							} else if (line.startsWith("reaction")) {
								layoutColumn++;
								layoutRow = 0;
								String[] props = line.split(";");
								String reactionType = null;
								String reactionName = null;
								String isFast = null;
								String isReversible = null;
								String annotation = "";

								Set<String> reactants = new HashSet<String>();
								Set<String> products = new HashSet<String>();
								Set<String> modifiers = new HashSet<String>();

								// extract the information about the reaction from the request
								for (String prop : props) {
									if (prop.startsWith("reactionName")) {
										reactionName = prop.substring(prop.indexOf("=") + 1);
									} else if (prop.startsWith("reactionType")) {
										reactionType = prop.substring(prop.indexOf("=") + 1);
									} else if (prop.startsWith("isFast")) {
										isFast = prop.substring(prop.indexOf("=") + 1);
									} else if (prop.startsWith("isReversible")) {
										isReversible = prop.substring(prop.indexOf("=") + 1);
									} else if (prop.startsWith("hasProduct")) {
										String product = prop.substring(prop.indexOf("=") + 1);
										
										if (allSpeciesNames.contains(product))
											products.add(product);
										else if (allSpeciesNames.contains(product.substring(0, 1).toLowerCase() + product.substring(1)))
											products.add(product.substring(0, 1).toLowerCase() + product.substring(1));
										else if (allSpeciesNames.contains(realNameMap.get(product))) 
											reactants.add(realNameMap.get(product));
										else if (allSpeciesNames.contains(realNameMap.get(product.substring(0, 1).toLowerCase() + product.substring(1))))
											reactants.add(realNameMap.get(product.substring(0, 1).toLowerCase() + product.substring(1)));
										
									} else if (prop.startsWith("hasReactant")) {
										String reactant = prop.substring(prop.indexOf("=") + 1);


										if (allSpeciesNames.contains(reactant))
											reactants.add(reactant);
										else if (allSpeciesNames.contains(reactant.substring(0, 1).toLowerCase()
												+ reactant.substring(1)))
											reactants.add(reactant.substring(0, 1).toLowerCase() + reactant.substring(1));
										else if (allSpeciesNames.contains((realNameMap.get(reactant)).substring(0, 1).toLowerCase() + (realNameMap.get(reactant)).substring(1))) {
											reactants.add(realNameMap.get(reactant));
										}
										else if (allSpeciesNames.contains(realNameMap.get(reactant.substring(0, 1).toUpperCase() + reactant.substring(1)))) {
											reactants.add(realNameMap.get(reactant.substring(0, 1).toUpperCase() + reactant.substring(1)));
										}
										
									} else if (prop.startsWith("hasModification")) {
										String modification = prop.substring(prop.indexOf("=") + 1);

										String[] mod = modification.split("__");

										if (allSpeciesNames.contains(mod[0])) {
											modifiers.add(modification);
										} else if (allSpeciesNames.contains(mod[0].substring(0, 1).toLowerCase() + mod[0].substring(1))) {
											modifiers.add(modification.substring(0, 1).toLowerCase() + modification.substring(1));
										}

									} else if (prop.startsWith("annotation")) {
										annotation = prop.substring(prop.indexOf("=") + 1);
									}
								}

								// if a reaction with this name is already present in the model, remove it
								if (allReactionsNames.contains(reactionName)) {
									for (int i = 0; i < allReactions.size(); i++) {
										PluginReaction alreadyPresentReaction = (PluginReaction) allReactions.get(i);
										if (alreadyPresentReaction.getName().equals(reactionName)) {
											pm.removeReaction(alreadyPresentReaction);
											plugin.notifySBaseDeleted(alreadyPresentReaction);
										}
									}
								}

								// create the new reaction, set all its attributes
								PluginReaction reac = new PluginReaction();
								reac.setName(reactionName);
								reac.setReactionType(reactionType);
								reac.setFast(Boolean.parseBoolean(isFast));
								reac.setReversible(Boolean.parseBoolean(isReversible));

								// add the names of all its reactants
								for (String reactant : reactants) {
									if (!reactant.equals(name)) {
										reac.addReactant(new PluginSpeciesReference(reac, pm.getSpecies(map.get(reactant)).getSpeciesAlias(0)));
									} else {
										reac.addReactant(new PluginSpeciesReference(reac, markedSpecies));
									}

								}

								// add the names of all its products
								for (String product : products) {
									if (!product.equals(name)) {
										reac.addProduct(new PluginSpeciesReference(reac, pm.getSpecies(map.get(product))
												.getSpeciesAlias(0)));
									} else {
										reac.addProduct(new PluginSpeciesReference(reac, markedSpecies));
									}
								}

								// add all its modifiers
								for (String mod : modifiers) {
									String[] modSplit = mod.split("__");

									PluginModifierSpeciesReference modRef = new PluginModifierSpeciesReference(reac, pm.getSpecies(map.get(modSplit[0])).getSpeciesAlias(0));
									modRef.setModificationType(modSplit[1]);
									reac.addModifier(modRef);
								}

								reac.setNotes(annotation);

								pm.addReaction(reac);
								plugin.notifySBaseAdded(reac);

							}

						}

						layoutColumn = 0;
						layoutRow = 0;

					} catch (MalformedURLException e2) {
						e2.printStackTrace();
					} catch (IOException e3) {
						e3.printStackTrace();
					}
				}
				
				setCursor(Cursor.DEFAULT_CURSOR);

			}

		});

		buttonPanel.add(loadButton);
		buttonPanel.add(new JLabel("       "));
		buttonPanel.add(new JLabel("       "));

		JButton saveButton = new JButton("Store");
		saveButton.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

				setCursor(Cursor.WAIT_CURSOR);
				
				ModelExtractor extractor = new ModelExtractor();

				try {
					PluginModel pm = plugin.getSelectedModel();

					PluginListOf selectedSpecieses = plugin.getSelectedSpeciesNode();
					Set<String> speciesNames = new HashSet<String>();

					int i = 0;

					/*
					 * get all selected specieses and add them together with all the available information to the object model. This
					 * makes the actual storing operations much easier
					 */
					while (selectedSpecieses.get(i) != null) {

						ReactionParticipant rp = new ReactionParticipant();
						PluginSpeciesAlias markedSpecies = (PluginSpeciesAlias) selectedSpecieses.get(i);

						rp.species = new Species(markedSpecies.getName());
						speciesNames.add(markedSpecies.getName());

						rp.species.speciesType = markedSpecies.getType();
						
						String name = markedSpecies.getName();
						
						// construct a request for all information about the marked species
						String reqURL = hostAdress + "store/species/x?type=" + markedSpecies.getType() + "&name=" + name
								+ "&hyp=" + markedSpecies.getHypothetical() + "&language=" + ExtractorPluginDialog.this.language;

						// only proteins have a protein type. retrieve this protein type also for them
						if (markedSpecies.getType().equals("PROTEIN")) {
							rp.species.proteinType = markedSpecies.getProtein().getType();
							reqURL += "&protType=" + markedSpecies.getProtein().getType();
						}

						PluginListOf test = markedSpecies.getModifications();
						int j = 0;
						while (test.get(j) != null) {
							reqURL += "&modification=" + ((PluginModification) test.get(j)).getState();
							j++;
						}
						
						reqURL += "&wiki=" + ExtractorPluginDialog.this.wikiUrl + "&namespace=" + ExtractorPluginDialog.this.namespace + "&language=" + ExtractorPluginDialog.this.language;
						reqURL += "&user=" + user + "&pass=" + pass;
						
						URL url;
						
						// here, the actual storing of the species to the wiki takes place
						try {
							url = new URL(reqURL);
							URLConnection conn = url.openConnection();

							BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
							String line;
							while ((line = rd.readLine()) != null) {
								System.out.println(line);
							}

						} catch (MalformedURLException e2) {
							e2.printStackTrace();
						} catch (IOException e3) {
							e3.printStackTrace();
						}

						extractor.specieses.add(rp);
						i++;
					}

					PluginListOf listOfReactions = pm.getListOfReactions();
					i = 0;

					/*
					 * get all reactions, save them to database. If products and/or reactants are already in the SB, interlink them
					 */
					while (listOfReactions != null && listOfReactions.get(i) != null) {
						
						PluginReaction pluginReaction = (PluginReaction) listOfReactions.get(i);
						boolean add = true;

						Reaction reaction = new Reaction();
						reaction.reactionName = pluginReaction.getName();
						reaction.reactionType = pluginReaction.getReactionType();
						reaction.isFast = pluginReaction.getFast();

						int j = 0;
						
						// iterate over all the reaction's products, add them to the reaction-object 
						PluginSpeciesReference temp = pluginReaction.getProduct(j);
						while (temp != null) {

							PluginListOf mods = temp.getAlias().getModifications();
							int k = 0;
							String modString = "";
							while (mods.get(k) != null) {
								// construct the correct name for the modified species
								modString += "_" + ((PluginModification) mods.get(k)).getState();
								k++;
							}
							
							// for all reactions, get all their products
							// check if this reaction should be stored, i.e. if a product or reactant is selected
							if (!speciesNames.contains(temp.getSpeciesInstance().getName()))
								add = false;

							ReactionParticipant rp = new ReactionParticipant(
									new Species(temp.getSpeciesInstance().getName()), temp.getSpeciesInstance().getCharge(),
									temp.getSpeciesInstance().getBoundaryCondition(), temp.getSpeciesInstance().getInitialAmount(), 
									temp.getSpeciesInstance().getInitialConcentration(), temp.getSpeciesInstance().getConstant(), modString);

							reaction.products.add(rp);

							temp = pluginReaction.getProduct(++j);

						}
						j = 0;

						// iterate over all the reaction's reactants, add them to the reaction-object
						temp = pluginReaction.getReactant(j);
						while (temp != null) {

							PluginListOf mods = temp.getSpeciesInstance().getSpeciesAlias(0).getModifications();
							int k = 0;
							String modString = "";
							while (mods.get(k) != null) {
								modString += "_" + ((PluginModification) mods.get(k)).getState();
								k++;
							}
							// if one of the products or reactans has not been selected, discard the reaction and do not store it.
							// Reactions are only stored if all their participants are selected
							if (!speciesNames.contains(temp.getSpeciesInstance().getName()))
								add = false;

							reaction.reactants.add(new ReactionParticipant(new Species(temp.getSpeciesInstance().getName()),
									temp.getSpeciesInstance().getCharge(), temp.getSpeciesInstance().getBoundaryCondition(),
									temp.getSpeciesInstance().getInitialAmount(), temp.getSpeciesInstance()
											.getInitialConcentration(), temp.getSpeciesInstance().getConstant(), modString));
							temp = pluginReaction.getReactant(++j);
						}

						reaction.isReversible = pluginReaction.getReversible();

						j = 0;

						PluginModifierSpeciesReference temp2 = pluginReaction.getModifier(j);
						while (temp2 != null) {

							Species modifier = new Species(temp2.getSpeciesInstance().getName());

							reaction.modifications.add(new Modification(pluginReaction.getModifier(j).getModificationType(),
									modifier));

							temp2 = pluginReaction.getModifier(++j);
						}

						// extractor contains only the reactions to be added
						if (add)
							extractor.reactions.add(reaction);

						i++;
					}

					// construct the request for storing a reaction
					for (Reaction rec : extractor.reactions) {
						String reqUrl = hostAdress + "store/reaction/?name=" + rec.reactionName + "&type=reaction"
								+ "&reactionType=" + rec.reactionType + "&isFast=" + rec.isFast + "&isReversible="
								+ rec.isReversible;
						i = 1;
						for (ReactionParticipant part : rec.products) {
							reqUrl += "&hasProduct=" + part.species.speciesName;
							if (part.modifications != null && !part.modifications.equals("") && !part.species.speciesName.contains("_modified_")) {
								reqUrl += "_modified" + part.modifications;
							}
						}

						i = 1;
						for (ReactionParticipant part : rec.reactants) {
							reqUrl += "&hasReactant=" + part.species.speciesName;
							if (part.modifications != null && !part.modifications.equals("") && !part.species.speciesName.contains("_modified_")) {
								reqUrl += "_modified" + part.modifications;
							}
						}

						for (Modification mod : rec.modifications) {
							reqUrl += "&hasModification=" + mod.modifier.speciesName + "__" + mod.modificationType;
						}
						reqUrl += "&user=" + user + "&pass=" + pass;
						
						reqUrl += "&wiki=" + ExtractorPluginDialog.this.wikiUrl + "&namespace=" + ExtractorPluginDialog.this.namespace + "&language=" + ExtractorPluginDialog.this.language;

						URL url;
						try {
							url = new URL(reqUrl);
							URLConnection conn = url.openConnection();

							BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
							String line;
							while ((line = rd.readLine()) != null) {
								System.out.println(line);
							}

						} catch (MalformedURLException e2) {
							e2.printStackTrace();
						} catch (IOException e3) {
							e3.printStackTrace();
						}
					}

				} catch (Exception ex) {
					ex.printStackTrace();
				}
				finally {
					setCursor(Cursor.DEFAULT_CURSOR);
				}

			}

		});

		buttonPanel.add(new JLabel(
				"<html>Store information about   <br>selected resources to the   <br>Semantic MediaWiki</html>"));

		buttonPanel.add(saveButton);

		wrapperPanel = new JPanel();
		BorderLayout wrapperLayout = new BorderLayout();
		wrapperPanel.setLayout(wrapperLayout);

		String s = "<html>This plugin supports you in storing to <br>and restoring CellDesigner-model-information <br>from a running SMW instance<br><br><br><br></html>";
		JLabel header = new JLabel(s);
		wrapperPanel.add(header, BorderLayout.NORTH);
		wrapperPanel.add(buttonPanel, BorderLayout.CENTER);

		return wrapperPanel;
	}

	private void setCursor(int cursorType) {
		wrapperPanel.setCursor(new Cursor(cursorType));
	}

	private static final long serialVersionUID = 0x665d2a92bdd642f1L;
	private ExtractorPlugin plugin;
	private JPanel buttonPanel;
	private JPanel wrapperPanel;
	private String user;
	private String pass;
	private String wikiUrl;
	private String namespace;
	private String language;
}
